package xx.iverson.school_manage.log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import xx.iverson.school_manage.entity.LogEntry;
import xx.iverson.school_manage.entity.User;
import xx.iverson.school_manage.mapper.LogsMapper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * xx.iverson.school_manage.log.MyBatisLoggingAspect
 * <p>
 * on 2024/9/15
 *
 * @author weijx
 */
@Aspect
@Component
public class MyBatisLoggingAspect {
    @Autowired
    private LogsMapper logsMapper;

    public MyBatisLoggingAspect(LogsMapper logsMapper) {
        this.logsMapper = logsMapper;
    }
    @Pointcut("@annotation(xx.iverson.school_manage.log.Loggable)")
    public void loggableMethods() {}

    @Around("loggableMethods()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Loggable annotation = method.getAnnotation(Loggable.class);

        Object result = null;
        try {
            // 获取操作人信息
            String operator = getOperatorFromSession();

            // 开始记录日志的时间点
            long startTime = System.currentTimeMillis();
            System.out.println("Method " + method.getName() + " start");

            // 获取方法参数
            Object[] args = joinPoint.getArgs();

            // 调用实际的方法
            result = joinPoint.proceed(args); // 继续执行方法

            // 结束记录日志的时间点
            long endTime = System.currentTimeMillis();
            System.out.println("Method " + method.getName() + " end, took " + (endTime - startTime) + " ms");

            // 记录日志到数据库
            saveLogToDatabase(annotation.value(), operator, true, "success");

            return result;
        } catch (Exception e) {
            saveLogToDatabase(annotation.value(), getOperatorFromSession(), false, e.getMessage());
            throw e;
        }
    }


    private void saveLogToDatabase(String description, String operator, boolean success, String failureReason) {
        LogEntry logEntry = new LogEntry();
        logEntry.setDescription(description);
        logEntry.setOperator(operator);
        logEntry.setOperation_time(new Date());
        logEntry.setSuccess(success);
        logEntry.setFailure_reason(failureReason);
        logsMapper.insertLog(logEntry);
    }

    @AfterThrowing(pointcut = "loggableMethods()", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
        // 可以在这里做额外的异常日志记录
    }
    private String getOperatorFromSession() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            HttpSession session = request.getSession();
            Object user = session.getAttribute("user");
            if (user != null) {
                // 假设User对象有一个getRealName方法
                return ((User) user).getRealName();
            }
        }
        return "未知"; // 如果没有找到，则返回一个默认值
    }
}